package src.com.susiqi.service.impl;

import ch.qos.logback.core.util.MD5Util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import src.com.susiqi.dto.LoginDto;
import src.com.susiqi.dto.UserDto;
import src.com.susiqi.dto.UserPageDto;
import src.com.susiqi.enity.Users;
import src.com.susiqi.mapper.UserMapper;
import src.com.susiqi.result.Result;
import src.com.susiqi.service.UserService;
import src.com.susiqi.utils.SecurePasswordEncryptor;
import src.com.susiqi.vo.UserVo;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static src.com.susiqi.constants.RedisConstants.USER_INFO_KEY;
import static src.com.susiqi.constants.RedisConstants.USER_INFO_TTL;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, Users> implements UserService {
    @Autowired
    private RedisTemplate<String,String> redis;



    @Override
    public Result login(LoginDto loginDto, HttpServletRequest request) {
        return null;
    }

    /**
     * 根据用户id获取用户信息
     * @param id 用户id
     * @return
     */
    @Override
    public Result getById(Long id) {
        String userCacheKey = USER_INFO_KEY + id;

        // 1. 尝试从 Redis 获取用户信息
        String userJson = redis.opsForValue().get(userCacheKey);
        if (StrUtil.isNotBlank(userJson)) {
            if (userJson.equals("{}")){
                return Result.fail("未知错误");
            }
            Users bean = JSONUtil.toBean(userJson, Users.class);
            return Result.success(bean);
        }

        // 2. 如果 Redis 中没有，则从数据库中查询
        Users user = baseMapper.selectById(id);
        if (ObjUtil.isNull(user)) {
            // 3. 缓存空字符串，防止缓存穿透
            redis.opsForValue().set(userCacheKey,"{}",USER_INFO_TTL, TimeUnit.MINUTES);
            return Result.fail("用户不存在");
        }

        // 4. 将数据放入redis
        String jsonStr = JSONUtil.toJsonStr(user);
        redis.opsForValue().set(userCacheKey,jsonStr,USER_INFO_TTL,TimeUnit.MINUTES);
        return Result.success(user);
    }

    /**
     * 根据用户id删除用户
     * @param id 用户的id
     * @return
     */
    @Override
    public Result deleteById(Long id) {
        // 1. 查询用户是否存在数据库
        Users user = baseMapper.selectById(id);
        if (ObjUtil.isNull(user)) {
            return Result.fail();
        }

        // 2.执行删除
        boolean b = removeById(id);
        if (!b){
            return Result.fail("删除失败");
        }

        // 3.清除缓存，返回结果
        clearUserCache(id);
        return Result.success();
    }

    /**
     * 新增或者修改用户
     * @param userDto
     * @return
     */
    @Override
    public Result saveOrUpdate(UserDto userDto) {
        // 1.判断参数是否有效
        if (ObjUtil.isEmpty(userDto)) {
            return Result.fail("参数不能为空");
        }

        Boolean isUpdate = false;
        Users user = new Users();
        BeanUtil.copyProperties(userDto,user);

        // 2.判断是更新还是新增
        if (ObjUtil.isNotNull(user.getId())) {
            isUpdate = true;
        }

        // 3.如果不是更新，设置一些默认值
        if (!isUpdate) {
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            String salt = SecurePasswordEncryptor.generateSalt();
            String passwordHash = SecurePasswordEncryptor.encrypt("123456", salt);
            user.setPassword_hash(passwordHash);
            user.setSalt(salt);
        }

        // 4.执行更新或者新增
        boolean b = saveOrUpdate(user);
        if (!b) {
            return Result.fail();
        }

        // 5.删除用户的缓存，等待下一次重建
        clearUserCache(user.getId());
        return Result.success();
    }

    /**
     * 分页查询用户
     * @param userPageDto
     * @return
     */
    @Override
    public Result getPage(UserPageDto userPageDto) {
        // 1.设置默认页码
        int pageNum = ObjUtil.isNull(userPageDto.getPageNum()) ? 1 : userPageDto.getPageNum();
        int pageSize = ObjUtil.isNull(userPageDto.getPageSize()) ? 1 : userPageDto.getPageSize();

        // 2.构建查询条件
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(StrUtil.isNotBlank(userPageDto.getRole()),Users::getRole,userPageDto.getRole())
                .like(StrUtil.isNotBlank(userPageDto.getUsername()),Users::getUsername,userPageDto.getUsername())
                .like(StrUtil.isNotBlank(userPageDto.getPhoneNumber()),Users::getPhoneNumber,userPageDto.getPhoneNumber())
                .orderByAsc(Users::getId);

        // 3.查询分页
        Page<Users> usersPage = baseMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        List<UserVo> userVos = userListToVo(usersPage.getRecords());
        Page<UserVo> userVoPage = new Page<>();
        BeanUtil.copyProperties(usersPage,userVoPage);
        userVoPage.setRecords(userVos);
        return Result.success(userVoPage);
    }

    //========================私有方法===============
    private void clearUserCache(long id){
        if (ObjUtil.isNull(id)){
            return;
        }
        String userCacheKey = USER_INFO_KEY+id;
        redis.delete(userCacheKey);
    }

    private List<UserVo> userListToVo(List<Users> users){
        if (ObjUtil.isEmpty(users)) {
            return new ArrayList<>();
        }

        List<UserVo> voList = users.stream().map(user -> {
            UserVo vo = new UserVo();
            BeanUtil.copyProperties(user, vo);
            return vo;
        }).collect(Collectors.toList());
        return voList;
    }

}
